package com.offics.loan.application.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.offics.loan.application.dto.file.FileUploadResponse;
import com.offics.loan.application.dto.user.*;
import com.offics.loan.domain.entity.User;
import com.offics.loan.domain.entity.UserInfo;
import com.offics.loan.domain.repository.UserInfoRepository;
import com.offics.loan.domain.repository.UserRepository;
import com.offics.loan.domain.service.SmsCodeDomainService;
import com.offics.loan.domain.service.UserDomainService;
import com.offics.loan.infrastructure.exception.BusinessException;
import com.offics.loan.infrastructure.service.FileStorageService;
import com.offics.loan.infrastructure.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 用户应用服务
 */
@Service
@RequiredArgsConstructor
public class UserApplicationService {

    private final UserRepository userRepository;
    private final UserInfoRepository userInfoRepository;
    private final UserDomainService userDomainService;
    private final AuthenticationManager authenticationManager;
    private final JwtUtils jwtUtils;
    private final SmsCodeDomainService smsCodeDomainService;
    private final FileStorageService fileStorageService;

    /**
     * 注册
     *
     * @param registerRequest 注册请求
     * @return 注册响应
     */
    @Transactional(rollbackFor = Exception.class)
    public RegisterResponse register(RegisterRequest registerRequest) {
        // 验证验证码
        boolean verified = smsCodeDomainService.verifyCode(registerRequest.getPhone(), registerRequest.getCode(), 1);
        if (!verified) {
            throw new BusinessException("验证码错误或已过期");
        }

        // 创建用户
        User user = new User();
        user.setUsername(registerRequest.getPhone());
        user.setPassword(registerRequest.getPassword());
        user.setPhone(registerRequest.getPhone());
        user.setStatus(1);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 注册用户
        User registeredUser = userDomainService.register(user);

        // 构建响应
        RegisterResponse response = new RegisterResponse();
        response.setId(registeredUser.getId());
        response.setUsername(registeredUser.getUsername());
        response.setPhone(registeredUser.getPhone());
        response.setEmail(registeredUser.getEmail());
        return response;
    }

    /**
     * 登录
     *
     * @param loginRequest 登录请求
     * @return 登录响应
     */
    public LoginResponse login(LoginRequest loginRequest) {
        // 认证
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
        );

        // 设置认证信息
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 生成JWT
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        String jwt = jwtUtils.generateToken(userDetails);

        // 获取用户信息
        Optional<User> optionalUser = userRepository.findByUsername(loginRequest.getUsername());
        if (optionalUser.isEmpty()) {
            throw new BusinessException("用户不存在");
        }

        User user = optionalUser.get();

        // 更新最后登录时间和IP
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(loginRequest.getIp());
        userRepository.update(user);

        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setToken(jwt);
        response.setId(user.getId());
        response.setUsername(user.getUsername());
        response.setPhone(user.getPhone());
        response.setEmail(user.getEmail());
        response.setRealName(user.getRealName());
        response.setAvatar(user.getAvatar());
        return response;
    }

    /**
     * 获取用户信息
     *
     * @param userId 用户ID
     * @return 用户信息响应
     */
    public UserInfoResponse getUserInfo(Long userId) {
        // 获取用户
        Optional<User> optionalUser = userRepository.findById(userId);
        if (optionalUser.isEmpty()) {
            throw new BusinessException("用户不存在");
        }

        User user = optionalUser.get();

        // 获取用户信息
        Optional<UserInfo> optionalUserInfo = userInfoRepository.findByUserId(userId);
        UserInfo userInfo = optionalUserInfo.orElse(new UserInfo());

        // 构建响应
        UserInfoResponse response = new UserInfoResponse();
        response.setId(user.getId());
        response.setUsername(user.getUsername());
        response.setPhone(user.getPhone());
        response.setEmail(user.getEmail());
        response.setRealName(user.getRealName());

        response.setAvatar(user.getAvatar());
        response.setStatus(user.getStatus());
        response.setLastLoginTime(user.getLastLoginTime());
        response.setLastLoginIp(user.getLastLoginIp());
        response.setCreateTime(user.getCreateTime());
        response.setUpdateTime(user.getUpdateTime());

        if (userInfo.getId() != null) {
            response.setIdCard(userInfo.getIdCard());
            response.setName(userInfo.getName());
            response.setIdCardFrontImage(userInfo.getIdCardFrontImage());
            response.setIdCardBackImage(userInfo.getIdCardBackImage());
            response.setIdCardHandImage(userInfo.getIdCardHandImage());
            response.setAlipayAccount(userInfo.getAlipayAccount());
            response.setAlipayScore(userInfo.getAlipayScore());
            response.setEducation(userInfo.getEducation());
            response.setCompanyName(userInfo.getCompanyName());
            response.setPosition(userInfo.getPosition());
            response.setCompanyPhone(userInfo.getCompanyPhone());
            response.setWorkYears(userInfo.getWorkYears());
            response.setCompanyAddress(userInfo.getCompanyAddress());
            response.setMonthlyIncome(userInfo.getMonthlyIncome());
            response.setResidenceAddress(userInfo.getResidenceAddress());
            response.setContact1Name(userInfo.getContact1Name());
            response.setContact1Phone(userInfo.getContact1Phone());
            response.setContact1Relation(userInfo.getContact1Relation());
            response.setContact2Name(userInfo.getContact2Name());
            response.setContact2Phone(userInfo.getContact2Phone());
            response.setContact2Relation(userInfo.getContact2Relation());
            response.setOtherData(userInfo.getOtherData());
        }

        return response;
    }

    /**
     * 更新用户信息
     *
     * @param updateUserInfoRequest 更新用户信息请求
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserInfo(UpdateUserInfoRequest updateUserInfoRequest) {

        System.out.println("@@@@@@@@@@@@@@@@@@@@@@" + updateUserInfoRequest.getOtherData());
        // 获取用户
        Optional<User> optionalUser = userRepository.findById(updateUserInfoRequest.getId());
        if (optionalUser.isEmpty()) {
            throw new BusinessException("用户不存在");
        }
        // 获取用户信息
        Optional<UserInfo> optionalUserInfo = userInfoRepository.findByUserId(updateUserInfoRequest.getId());
        UserInfo userInfo = optionalUserInfo.orElse(new UserInfo());
        userInfo.setUserId(updateUserInfoRequest.getId());
        BeanUtils.copyProperties(updateUserInfoRequest, userInfo);

        // 更新用户信息
        return userDomainService.updateUserInfo(userInfo);
    }

    /**
     * 更新用户信息并返回
     *
     * @param updateUserInfoRequest 更新用户信息请求
     * @return 用户信息响应
     */
    @Transactional(rollbackFor = Exception.class)
    public UserInfoResponse updateUserInfoAndReturn(UpdateUserInfoRequest updateUserInfoRequest) {
        // 更新用户信息
        boolean result = updateUserInfo(updateUserInfoRequest);
        if (!result) {
            throw new BusinessException("更新用户信息失败");
        }

        // 返回用户信息
        return getUserInfo(updateUserInfoRequest.getId());
    }

    /**
     * 修改密码
     *
     * @param changePasswordRequest 修改密码请求
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(ChangePasswordRequest changePasswordRequest) {
        return userDomainService.changePassword(
                changePasswordRequest.getUserId(),
                changePasswordRequest.getOldPassword(),
                changePasswordRequest.getNewPassword()
        );
    }

    /**
     * 重置密码
     *
     * @param resetPasswordRequest 重置密码请求
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(ResetPasswordRequest resetPasswordRequest) {
        return userDomainService.resetPassword(
                resetPasswordRequest.getUserId(),
                resetPasswordRequest.getNewPassword()
        );
    }

    /**
     * 分页查询用户
     *
     * @param pageRequest 分页请求
     * @return 分页结果
     */
    public IPage<UserInfoResponse> page(UserPageRequest pageRequest) {
        // 创建分页参数
        Page<User> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());

        // 分页查询
        IPage<User> userPage = userRepository.findPage(
                page,
                pageRequest.getUsername(),
                pageRequest.getPhone(),
                pageRequest.getStatus()
        );

        // 转换结果
        return userPage.convert(user -> {
            UserInfoResponse response = new UserInfoResponse();
            BeanUtils.copyProperties(user, response);
            return response;
        });
    }

    /**
     * 启用用户
     *
     * @param userId 用户ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean enable(Long userId) {
        return userDomainService.enable(userId);
    }

    /**
     * 禁用用户
     *
     * @param userId 用户ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean disable(Long userId) {
        return userDomainService.disable(userId);
    }

    /**
     * 上传文件
     *
     * @param file 文件
     * @param fileType 文件类型（例如：idCardFront, idCardBack, idCardHand）
     * @param userId 用户ID
     * @return 文件上传响应
     */
    public FileUploadResponse uploadFile(MultipartFile file, String fileType, Long userId) {
        // 验证文件类型
        if (!isValidFileType(file)) {
            throw new BusinessException("不支持的文件类型，仅支持图片格式");
        }

        // 验证文件大小
        if (file.getSize() > 5 * 1024 * 1024) { // 5MB
            throw new BusinessException("文件大小不能超过5MB");
        }

        // 存储文件
        String subDir = "user/" + userId + "/" + fileType;
        String fileUrl = fileStorageService.storeFile(file, subDir);

        // 构建响应
        FileUploadResponse response = new FileUploadResponse();
        response.setFileUrl(fileUrl);
        response.setFileName(file.getOriginalFilename());
        response.setFileType(file.getContentType());
        response.setFileSize(file.getSize());

        return response;
    }

    /**
     * 验证文件类型是否为图片
     *
     * @param file 文件
     * @return 是否为图片
     */
    private boolean isValidFileType(MultipartFile file) {
        String contentType = file.getContentType();
        return contentType != null && contentType.startsWith("image/");
    }

    /**
     * 删除用户
     *
     * @param userId 用户ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long userId) {
        return userDomainService.delete(userId);
    }

    /**
     * 发送短信验证码
     *
     * @param request 发送短信验证码请求
     * @return 发送短信验证码响应
     */
    public SendSmsCodeResponse sendSmsCode(SendSmsCodeRequest request) {
        // 如果是重置密码类型，需要检查手机号是否存在
        if (request.getType() == 3) {
            Optional<User> optionalUser = userRepository.findByPhone(request.getPhone());
            if (optionalUser.isEmpty()) {
                throw new BusinessException("该手机号未注册");
            }
        }

        // 生成并发送验证码
        smsCodeDomainService.generateCode(request.getPhone(), request.getType());

        // 构建响应
        SendSmsCodeResponse response = new SendSmsCodeResponse();
        // 手机号脱敏处理
        response.setPhone(maskPhone(request.getPhone()));
        response.setExpireTime(smsCodeDomainService.getExpireTime());
        return response;
    }

    /**
     * 通过手机验证码重置密码
     *
     * @param request 通过手机验证码重置密码请求
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPasswordByPhone(ResetPasswordByPhoneRequest request) {
        // 验证验证码
        boolean verified = smsCodeDomainService.verifyCode(request.getPhone(), request.getCode(), 3);
        if (!verified) {
            throw new BusinessException("验证码错误或已过期");
        }

        // 根据用户名查询用户
        Optional<User> optionalUser = userRepository.findByUsername(request.getPhone());
        if (optionalUser.isEmpty()) {
            throw new BusinessException("用户不存在");
        }

        User user = optionalUser.get();

        // 验证手机号是否匹配
        if (!request.getPhone().equals(user.getPhone())) {
            throw new BusinessException("用户名与手机号不匹配");
        }

        // 重置密码
        return userDomainService.resetPassword(user.getId(), request.getNewPassword());
    }

    /**
     * 手机号脱敏处理
     *
     * @param phone 手机号
     * @return 脱敏后的手机号
     */
    private String maskPhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
}
